#include "mystdio.h"

MyFile *my_fopen(const char *path, const char *mode)
{
  int flags = 0;  
  if(strcmp(mode,"w") == 0) flags = O_WRONLY | O_CREAT | O_TRUNC;
  else if(strcmp(mode,"r") == 0) flags = O_RDONLY;
  else if(strcmp(mode,"a") == 0) flags = O_WRONLY | O_CREAT | O_APPEND;
  else if(strcmp(mode,"rb") == 0) flags = O_RDONLY;
  else if(strcmp(mode,"wb") == 0) flags = O_WRONLY | O_CREAT | O_TRUNC;
  else if(strcmp(mode,"ab") == 0) flags = O_APPEND | O_WRONLY;
  else if(strcmp(mode,"r+") == 0) flags = O_RDWR;
  else if(strcmp(mode,"w+") == 0) flags = O_RDWR | O_CREAT | O_TRUNC;
  else if(strcmp(mode,"a+") == 0) flags = O_RDWR | O_CREAT | O_APPEND;
  else if(strcmp(mode,"rb+") == 0) flags = O_RDWR;
  else if(strcmp(mode,"wb+") == 0) flags = O_RDWR | O_CREAT | O_TRUNC;
  else if(strcmp(mode,"ab+") == 0) flags = O_RDWR | O_CREAT | O_APPEND;
  
  int Fd = 0;

  if(flags & O_CREAT)
  {
    mode_t m = 0666;
    Fd = open(path,flags,m);
  }
  else Fd = open(path,flags);
  
  if(Fd < 0)
    return NULL;

  MyFile* myfile = (MyFile*)malloc(sizeof(MyFile));
  if(myfile == NULL)
  {
    close(Fd);
    return NULL;
  }

  myfile->fd = Fd;
  memset(myfile->outbuffer,'0',sizeof(myfile->outbuffer));
  myfile->current = 0;
  myfile->flag = 0;
  myfile->flag |= BUFF_LINE;
  return myfile;
}

size_t my_fwrite(const void *ptr, size_t size, size_t nmemb,MyFile* stream)
{
  if(stream->current == MAX)
    my_fflush(stream);

  int user_size = size * nmemb;
  int my_size = MAX - stream->current;
  int writen = 0;
  if(user_size > my_size)
  {
    writen = my_size;
    memcpy(stream->outbuffer,ptr,writen);
    stream->current += writen;
  }
  else
  {
    writen = user_size;
    memcpy(stream->outbuffer,ptr,writen);
    stream->current += writen;
  }
  
  if(stream->flag & BUFF_ALL)
  {
    if(stream->current == MAX) my_fflush(stream);  
  }
  else if(stream->flag & BUFF_LINE) 
  {
    if(stream->outbuffer[stream->current - 1] == '\n') my_fflush(stream);
  }
  else
  {
    //TODO  不进行刷新，减少IO次数，提高效率
  }
  return writen;
}
int my_fflush(MyFile* stream)
{
  assert(stream);
  write(stream->fd,stream->outbuffer,stream->current);
  memset(stream->outbuffer,'0',sizeof(stream->outbuffer));
  stream->current = 0;
  
  fsync(stream->fd);
  return 0;
}

int my_fclose(MyFile* fp)
{
  assert(fp);
  if(fp->current != 0)
    my_fflush(fp);
  close(fp->fd);
  free(fp);
  fp = NULL;
  return 0;
}

//int my_printf(const char *format, ...)
//{
//  va_list ap;
//  va_start(ap,format);
//  int ret = 0;
//  while(*format)//遍历str
//  {
//    char* s = NULL;
//    if(*format == '%')
//    {
//      format++;
//      if(*format == 'd')
//      {
//        int d = va_arg(ap,int);//取参数列表对应值
//        printf("%d",d);
//        while(d)
//        {
//          ++ret;
//          d /= 10;
//        }
//      }
//      else if(*format == 's')
//      {
//        s = va_arg(ap,char*);
//        while(*s)
//        {
//          putchar(*s);
//          ++ret;
//          ++s;
//        }
//      }
//      else if(*format == 'c')
//      {
//        putchar(va_arg(ap,char));
//        ret++;
//      }
//    }
//    else
//    {
//      putchar(*format);
//      format++;
//      ret++;
//    }
//  }
//  va_end(ap);  
//  return ret;
//}

int my_printf(const char* format, ...)
{
  if(format == NULL) return 1;
	va_list ap;
	va_start(ap, format);
	int ret = 0;
	while (*format)//遍历str
	{
		char* s = NULL;
		if (*format == '%')
		{
			format++;
			if (*format == 'd')
			{
				int d = va_arg(ap, int);//取参数列表对应值
				printf("%d",d);
				while (d)
				{
					++ret;
					d /= 10;
				}
			}
			else if (*format == 's')
			{
				s = va_arg(ap, char*);
				while (*s)
				{
					putchar(*s);
					++ret;
					++s;
				}
			}
			else if (*format == 'c')
			{
				putchar(va_arg(ap,int));
				ret++;
			}
			format++;
		}
		else
		{
			putchar(*format);
			format++;
			ret++;//一个中文加两次导致误差,一个中文两个字符组成
		}
	}
	va_end(ap);
	return ret;
}

